package com.detrum.usbdevice.fragment;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.SurfaceTexture;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;

import com.detrum.base.BaseFinal;
import com.detrum.base.BaseStatic;
import com.detrum.base.ServiceStatic;
import com.detrum.bean.FileBean;
import com.detrum.sqlite.SqliteMediaOperation;
import com.detrum.usbdevice.R;
import com.detrum.utils.MyMethod;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link PreviewFragment.OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link PreviewFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class PreviewFragment extends Fragment implements TextureView.SurfaceTextureListener{

    private OnFragmentInteractionListener mListener;

    private TextureView textureView;
    private SurfaceTexture surfaceTexture;
    private Surface mSurface;

    private MediaCodec mCodec;
    private final static String MIME_TYPE = "video/avc"; // H.264 Advanced Video
    private int w = 720, h = 480;

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        surfaceTexture = surface;
        mSurface = new Surface(surfaceTexture);
        initCodec();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        mCodec.release();
        mCodec = null;
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    public static PreviewFragment newInstance() {
        PreviewFragment fragment = new PreviewFragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_preview, container, false);
        initView(view);
        BaseStatic.savaInfoToSD("PreviewFragment onCreateView");
        return view;
    }

    private void initCodec() {
        try {
            mCodec = MediaCodec.createDecoderByType(MIME_TYPE);
        } catch (IOException e) {
            e.printStackTrace();
        }
        MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE,
                w, h);
        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
        mCodec.configure(mediaFormat, mSurface,
                null, 0);
        mCodec.start();
        BaseStatic.savaInfoToSD("PreviewFragment initCodec");
        mListener.StartReceive();
    }

    /**
     * 图像解码
     *
     * @param buf    图像数据
     * @param length 数据长度
     */
    private void DecodeVideo(byte[] buf, int offset, int length, long pts) {
        if (mCodec != null) {
            try {
                ByteBuffer[] inputBuffers = mCodec.getInputBuffers();
                //等待时间，0->不等待，-1->一直等待
                long kTimeOutUs = 0;
                int inputBufferIndex = mCodec.dequeueInputBuffer(kTimeOutUs);
                if (inputBufferIndex >= 0) {
                    ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
                    inputBuffer.clear();
                    inputBuffer.put(buf, 0, length);
                    mCodec.queueInputBuffer(inputBufferIndex, offset, length, pts, 0);
                }else{
                    BaseStatic.savaInfoToSD("PreviewFragment inputBufferIndex = "+inputBufferIndex+"\n");
                }
                // Get output buffer index
                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                int outputBufferIndex = mCodec.dequeueOutputBuffer(bufferInfo, kTimeOutUs);
                if (outputBufferIndex >= 0) {
                    boolean doRender = (bufferInfo.size != 0);
                    mCodec.releaseOutputBuffer(outputBufferIndex, doRender);
                }else{
                    BaseStatic.savaInfoToSD("PreviewFragment outputBufferIndex = "+outputBufferIndex+"\n");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    public void setData(byte[] bys, int offset, int length){
        DecodeVideo(bys,offset,length,0);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onResume() {
        super.onResume();
        if(!ServiceStatic.isStartUsbPreview){
            mListener.StartReceive();
        }
    }

    private void initView(View view) {
        textureView = view.findViewById(R.id.textureView);
        textureView.setSurfaceTextureListener(this);
        textureView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(!ServiceStatic.isStartUsbPreview){
                    mListener.StartReceive();
                }else{
                    mListener.onClick();
                }
            }
        });
    }

    public void setCapture() {
        if (textureView != null) {
            Bitmap bitmap = textureView.getBitmap();
            new SavePic(bitmap).start();
        }
    }
    private int local =0;
    class SavePic extends Thread{
        Bitmap bitmap;
        protected SavePic(Bitmap bitmap){
            this.bitmap = bitmap;
        }
        @Override
        public void run() {
            super.run();
            long fileTime = System.currentTimeMillis();
            final String filePath = BaseStatic.MediaPath + "/"+paserTime(fileTime) + ".jpg";
            File file = new File(filePath);
            try {
                FileOutputStream fos = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                fos.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(BaseFinal.CurrentDeviceName.equals("IWT-AGS58")){
                local=2;
            }
            FileBean bean = new FileBean(null,file.getName(),null,filePath,null,file.length(),fileTime,0,local,0);
            SqliteMediaOperation.getInstence(getActivity()).Insert(bean);
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    MyMethod.ShowDialog(getActivity(), R.string.captureSuccess);
                }
            });

        }
    }

    private static String paserTime(long milliseconds) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        return format.format(new Date(milliseconds));
    }


    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        void onFragmentInteraction(Uri uri);
        void onClick();
        void StartReceive();
    }
}
